package executor

import (
	"context"
	"math/big"

	"github.com/adwindone/sdk-go/log"
	"github.com/adwindone/sdk-go/model/blockchain"
	"github.com/adwindone/sdk-go/model/common"
	"github.com/adwindone/sdk-go/model/evm"
	"github.com/adwindone/sdk-go/model/executor"
	"github.com/adwindone/sdk-go/model/request"
	"github.com/adwindone/sdk-go/model/response"

	"go.uber.org/zap"
	grpc "google.golang.org/grpc"
)

// PeopleChainExecutor provides interfaces for contract, account, and transaction execution.
type PeopleChainExecutor interface {
	// GetAbi returns the contract ABI information for the given address.
	GetAbi(ctx context.Context, address string) (string, error)
	// GetCode returns the contract bytecode for the given contract address.
	GetCode(ctx context.Context, address string) (string, error)
	// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
	GetTransactionReceipt(ctx context.Context, txHash string) (*response.Receipt, error)
	// GetBalance returns the account balance for the given address.
	GetBalance(ctx context.Context, address string) (*big.Int, error)
	// GetTransactionCount returns the number of transactions sent from the account address.
	GetTransactionCount(ctx context.Context, address string) (*big.Int, error)
	// EstimateQuota estimates the quota consumed by executing a transaction.
	EstimateQuota(ctx context.Context, crt *request.CallTransaction) (*big.Int, error)
	// GetReceiptProof returns the ReceiptProof information of the transaction by transaction hash.
	GetReceiptProof(ctx context.Context, txHash string) (*evm.ReceiptProof, error)
	// GetRootsInfo returns the RootsInfo for the given block height.
	GetRootsInfo(ctx context.Context, blockNumber uint64) (*evm.RootsInfo, error)
	// Call returns the chain data for the given call transaction.
	Call(ctx context.Context, crt *request.CallTransaction) ([]byte, error)
	// Exec executes the given transactions and returns the hash response.
	Exec(ctx context.Context, rtxs []*request.Transaction, header *blockchain.BlockHeader, blockNumber uint64, version uint32, proof []byte, stateRoot []byte) (*common.HashResponse, error)
}

type peopleChainExecutorManage struct {
	evmService      evm.RPCServiceClient
	executorService executor.ExecutorServiceClient
	log             *zap.Logger
}

var _ PeopleChainExecutor = (*peopleChainExecutorManage)(nil)

// NewPeopleChainExecutorManage creates a new PeopleChainExecutor instance.
func NewPeopleChainExecutorManage(cc *grpc.ClientConn) *peopleChainExecutorManage {
	return &peopleChainExecutorManage{
		evmService:      evm.NewRPCServiceClient(cc),
		executorService: executor.NewExecutorServiceClient(cc),
		log:             log.NewLogger(log.SetAppName("executor")),
	}
}
